package com.example.bluetooth.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.bluetooth.MyApp;
import com.example.bluetooth.R;
import com.example.bluetooth.retrofit.Api;
import com.example.bluetooth.retrofit.Result;
import com.google.gson.Gson;
import com.inuker.bluetooth.library.BluetoothClient;
import com.inuker.bluetooth.library.beacon.Beacon;
import com.inuker.bluetooth.library.connect.options.BleConnectOptions;
import com.inuker.bluetooth.library.search.SearchRequest;
import com.inuker.bluetooth.library.search.SearchResult;
import com.inuker.bluetooth.library.search.response.SearchResponse;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {

    private BluetoothClient mClient;

    private static final String TAG = "bluetooth";
    private LinearLayout llLoading;
    private TextView tvTip;
    private TextView tvInfo;
    private Button btnOpen;
    private Button btnClose;
    private TextView tvConnect;
    private RelativeLayout rlDevices;
    private static final String name = "XD";
    private static final String mac = "20:19:09:27:17:63";
    private Context context;
    private Button btnBind;
    private Button btnUnBind;
    private Button btnQuit;
    private Button btnScan;
    private Button btnClearCache;
    private boolean isConnected = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("控制中心");
        initView();

        mClient = new BluetoothClient(this);

        scanDevices();

    }

    private void initView() {
        context = this;
        btnClose = findViewById(R.id.btn_close);
        btnOpen = findViewById(R.id.btn_open);
        tvInfo = findViewById(R.id.tv_info);
        tvTip = findViewById(R.id.tv_tip);
        tvConnect = findViewById(R.id.tv_connect);
        llLoading = findViewById(R.id.ll_loading);
        rlDevices = findViewById(R.id.rl_devices);
        btnBind = findViewById(R.id.btn_bind);
        btnUnBind = findViewById(R.id.btn_unbind);
        btnQuit = findViewById(R.id.btn_quit);
        btnScan = findViewById(R.id.btn_scan);
        btnClearCache = findViewById(R.id.btn_clear_cache);

        BleConnectOptions options = new BleConnectOptions.Builder()
                .setConnectRetry(3)   // 连接如果失败重试3次
                .setConnectTimeout(30000)   // 连接超时30s
                .setServiceDiscoverRetry(3)  // 发现服务如果失败重试3次
                .setServiceDiscoverTimeout(20000)  // 发现服务超时20s
                .build();
        tvConnect.setOnClickListener(v -> {
            connect(mac);
        });
        btnClose.setOnClickListener(v -> {
            if (!isConnected) {
                Toast.makeText(context, "请先连接设备", Toast.LENGTH_SHORT).show();
                return;
            }
            sendCommand("CC");
            Toast.makeText(context, "已关闭", Toast.LENGTH_SHORT).show();
        });
        btnOpen.setOnClickListener(v -> {
            if (!isConnected) {
                Toast.makeText(context, "请先连接设备", Toast.LENGTH_SHORT).show();
                return;
            }
            sendCommand("AA");
            Toast.makeText(context, "已开启", Toast.LENGTH_SHORT).show();
        });
        btnBind.setOnClickListener(v -> {
            Map<String, String> map = new HashMap<>(5);
            map.put("name", (String) MyApp.map.get("name"));
            map.put("btId", mac);
            RequestBody body = FormBody.create(MediaType.parse("application/json; charset=utf-8"), new Gson().toJson(map));
            //接口对象实例调用相关接口，获得Observable对象
            Api api = MyApp.retrofit.create(Api.class);
            Call<Result> login = api.bind(body);
            login.enqueue(new Callback<Result>() {
                @Override
                public void onResponse(Call<Result> call, Response<Result> response) {
                    Result res = response.body();
                    if (res.getCode() == 20001) {
                        Toast.makeText(context, res.getMsg(), Toast.LENGTH_SHORT).show();
                    } else if (res.getCode() == 10001) {
                        Toast.makeText(context, "绑定成功", Toast.LENGTH_SHORT).show();
                        SharedPreferences sp = getSharedPreferences("App", MODE_PRIVATE);
                        SharedPreferences.Editor edit = sp.edit();
                        edit.putBoolean("isBind", true);
                        edit.apply();
                    }
                }

                @Override
                public void onFailure(Call<Result> call, Throwable t) {
                    Toast.makeText(context, "绑定失败，请检查网络", Toast.LENGTH_SHORT).show();
                }
            });
        });
        btnUnBind.setOnClickListener(v -> {
            Map<String, String> map = new HashMap<>(5);
            map.put("name", (String) MyApp.map.get("name"));
            map.put("btId", mac);
            RequestBody body = FormBody.create(MediaType.parse("application/json; charset=utf-8"), new Gson().toJson(map));
            //接口对象实例调用相关接口，获得Observable对象
            Api api = MyApp.retrofit.create(Api.class);
            Call<Result> login = api.unbind(body);
            login.enqueue(new Callback<Result>() {
                @Override
                public void onResponse(Call<Result> call, Response<Result> response) {
                    Result res = response.body();
                    if (res.getCode() == 20001) {
                        Toast.makeText(context, res.getMsg(), Toast.LENGTH_SHORT).show();
                    } else if (res.getCode() == 10001) {
                        Toast.makeText(context, "解绑成功", Toast.LENGTH_SHORT).show();
                        SharedPreferences sp = getSharedPreferences("App", MODE_PRIVATE);
                        SharedPreferences.Editor edit = sp.edit();
                        edit.putBoolean("isBind", false);
                        edit.apply();
                    }
                }

                @Override
                public void onFailure(Call<Result> call, Throwable t) {
                    Toast.makeText(context, "解绑失败，请检查网络", Toast.LENGTH_SHORT).show();
                }
            });
        });

        btnScan.setOnClickListener(v -> {
            llLoading.setVisibility(View.VISIBLE);
            scanDevices();
        });

        btnQuit.setOnClickListener(v -> {
            SharedPreferences sp = getSharedPreferences("App", MODE_PRIVATE);
            SharedPreferences.Editor edit = sp.edit();
            edit.putBoolean("isLogin", false);
            edit.apply();
            Intent intent = new Intent(context, LoginActivity.class);
            startActivity(intent);
            finish();
        });

        btnClearCache.setOnClickListener(v -> {
            SharedPreferences sp = getSharedPreferences("App", MODE_PRIVATE);
            SharedPreferences.Editor edit = sp.edit();
            edit.clear();
            edit.apply();
        });
    }

    private BluetoothAdapter bluetoothAdapter;
    private BluetoothSocket btSocket = null;
    private OutputStream outStream = null;
    public InputStream inStream = null;
    private UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    /**
     * 连接蓝牙
     **/
    public void connect(String address) {
        new Thread(() -> {
            try {
                connectBluetooth(address);

            } catch (IOException e) {
                Log.d(TAG, "蓝牙配对失败了");
                runOnUiThread(() -> Toast.makeText(context, "蓝牙连接失败", Toast.LENGTH_SHORT).show());
            }
        }).start();
    }

    public void close() {
        try {
            btSocket.close();
        } catch (Exception e2) {
            // Log .e(TAG,"ON RESUME: Unable to close socket during connection failure", e2);
        }
    }

    private void sendCommand(String command) {
        try {
            outStream.write(command.getBytes());
        } catch (IOException e) {
            runOnUiThread(() -> {
                Toast.makeText(context, "指令发送失败", Toast.LENGTH_SHORT).show();
            });
        }
    }

    private void connectBluetooth(String address) throws IOException {
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
        btSocket = device.createRfcommSocketToServiceRecord(uuid);
        bluetoothAdapter.cancelDiscovery();

        btSocket.connect();
        runOnUiThread(() -> {
            isConnected = true;
            Toast.makeText(context, "蓝牙连接成功", Toast.LENGTH_SHORT).show();
            tvConnect.setText("已连接");
            tvConnect.setOnClickListener(null);
        });
        outStream = btSocket.getOutputStream();
        inStream = btSocket.getInputStream();
    }

    private void scanDevices() {
        SearchRequest request = new SearchRequest.Builder()
                .searchBluetoothLeDevice(3000, 3)   // 先扫BLE设备3次，每次3s
                .searchBluetoothClassicDevice(5000) // 再扫经典蓝牙5s
                .searchBluetoothLeDevice(2000)      // 再扫BLE设备2s
                .build();

        mClient.search(request, new SearchResponse() {
            @Override
            public void onSearchStarted() {
                llLoading.setVisibility(View.VISIBLE);
            }

            @Override
            public void onDeviceFounded(SearchResult device) {
                Beacon beacon = new Beacon(device.scanRecord);
                Log.d("test", String.format("beacon for %s\n%s\n%s", device.getAddress(), beacon.toString(), device.getName()));
                if (mac.equals(device.getAddress())) {
                    tvInfo.setText(device.getName() + "  " + device.getAddress());
                    rlDevices.setVisibility(View.VISIBLE);

                    SharedPreferences app = getSharedPreferences("App", MODE_PRIVATE);
                    boolean isBind = app.getBoolean("isBind", false);
                    if (isBind) {
                        connect(mac);
                    }
                }
            }

            @Override
            public void onSearchStopped() {
                llLoading.setVisibility(View.GONE);
            }

            @Override
            public void onSearchCanceled() {

            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        close();
    }
}
